from enum import Enum
from .color import *
import time
import inspect
from typing import Callable


__all__ = [
    "LogLevel",
    "Logger",
]


class LogLevel(Enum):
    """
    系统日志等级枚举
    """
    DEBUG = 0
    INFO = 1
    ERROR = 2


class Logger:
    """
    日志系统
    """

    def __init__(self, project_root_dir: str = ""):
        """
        :param project_root_dir: 项目根目录
        """
        # 共有属性

        # 私有属性
        self._project_root_dir: str = project_root_dir   #绝对路径中需要过滤掉的内容
        self._log_level: LogLevel = LogLevel.DEBUG
        self._is_save: bool = False
        self._is_print: bool = True
        self._is_show_alarm: bool = True
        self._is_show_user: bool = True

    def set_log_leve(self, log_level: LogLevel):
        """
        设置日志等级
        :param log_level:
        :return:
        """
        self._log_level = log_level

    def set_is_save_log(self, is_save: bool) -> None:
        """
        设置是否存储到数据库中
        :param is_save: 是否保存
        :return:
        """
        self._is_save = is_save

    def set_is_print_log(self, is_print: bool) -> None:
        """
        设置是否打印到控制台
        :param is_print: 是否打印
        :return:
        """
        self._is_print = is_print

    def set_is_show_user(self, is_show: bool) -> None:
        """
        设置是否显示用户操作打印结果
        :param is_show: 是否显示
        :return:
        """
        self._is_show_user = is_show

    def set_is_show_alarm(self, is_show: bool) -> None:
        """
        设置是否显示报警打印结果
        :param is_show: 是否显示
        :return:
        """
        self._is_show_alarm = is_show

    @property
    def log_level(self) -> LogLevel:
        """
        获取日志等级
        :return: 日志等级
        """
        return self._log_level

    @property
    def is_save_log(self) -> bool:
        """
        持久化存储日志开关
        :return: 是否保存
        """
        return self._is_save

    @property
    def is_print_log(self) -> bool:
        """
        控制台打印开关
        :return: 是否打印
        """
        return self._is_print

    @property
    def is_show_user(self) -> bool:
        """
        :return: 是否显示
        """
        return self._is_show_user

    @property
    def is_show_alarm(self) -> bool:
        """
        :return: 是否显示
        """
        return self._is_show_alarm

    def user(self, msg):
        """
        采用青色打印
        :return:
        """
        if self._is_show_user:
            # 获取调用栈
            stack = inspect.stack()[1]
            # 获取调用文件路径
            calling_file = stack.filename.replace("\\", "/").replace(self._project_root_dir, "")
            # 获取调用行号
            calling_line = stack.lineno
            if self._is_print:
                self._print_head(print_cyan, "[USER  ]", calling_file, calling_line, msg)

    def alarm(self, msg):
        """
        采用青色打印
        :return:
        """
        if self._is_show_alarm:
            # 获取调用栈
            stack = inspect.stack()[1]
            # 获取调用文件路径
            calling_file = stack.filename.replace("\\", "/").replace(self._project_root_dir, "")
            # 获取调用行号
            calling_line = stack.lineno
            if self._is_print:
                self._print_head(print_cyan, "[ALARM]", calling_file, calling_line, msg)

    def debug(self, msg):
        """
        采用蓝色打印
        :return:
        """
        if self._log_level.value == LogLevel.DEBUG.value:
            # 获取调用栈
            stack = inspect.stack()[1]
            # 获取调用文件路径
            calling_file = stack.filename.replace("\\", "/").replace(self._project_root_dir, "")
            # 获取调用行号
            calling_line = stack.lineno

            if self._is_print:
                self._print_head(print_blue, "[DEBUG]", calling_file, calling_line, msg)

            if self._is_save:
                pass

    def info(self, msg):
        """
        采用绿色打印
        :return:
        """
        if self._log_level.value <= LogLevel.INFO.value:
            # 获取调用栈
            stack = inspect.stack()[1]
            # 获取调用文件路径
            calling_file = stack.filename.replace("\\", "/").replace(self._project_root_dir, "")
            # 获取调用行号
            calling_line = stack.lineno

            if self._is_print:
                self._print_head(print_green, "[INFO   ]", calling_file, calling_line, msg)

            if self._is_save:
                pass

    def warning(self, msg):
        """
        采用红色打印
        :return:
        """
        if self._log_level.value <= LogLevel.ERROR.value:
            # 获取调用栈
            stack = inspect.stack()[1]
            # 获取调用文件路径
            calling_file = stack.filename.replace("\\", "/").replace(self._project_root_dir, "")
            # 获取调用行号
            calling_line = stack.lineno

            if self._is_print:
                self._print_head(print_red, "[WARNING]", calling_file, calling_line, msg)

            if self._is_save:
                pass

    @staticmethod
    def _get_timestamp() -> str:
        """
        获取时间戳
        :return: 时间戳
        """
        return time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())

    def _print_head(self, print_def: Callable, flag:str, calling_file:str, calling_line:int, msg: str) -> None:
        """
        打印头部
        :param print_def: 打印对象
        :return:
        """
        print_def(
            self._get_timestamp() + \
            "  " + \
            flag + \
            "  " + \
            'File "' + calling_file + '", line ' + str(calling_line)
        )
        print(msg)
